home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / UTILITY / MIR105.ARJ / MIR_WP51.EXE / lha / A_BYTES.C < prev    next >
Text File  |  1992-05-02  |  11KB  |  339 lines

  1. /*
  2.  *  usage:  a_bytes [ /L ] file_name[s]
  3.  *
  4.  * A_BYTES  Analyze the bytes (characters) used within any file, report
  5.  *          the frequency of each byte present.  If the location flag /L
  6.  *          is set, include offsets of the first 8 occurrences of each
  7.  *          byte pattern present.
  8.  *
  9.  *  input:  Any file[s] whatsoever.
  10.  *
  11.  *  output: file_name.BYT which contains up to 256 lines, one line for
  12.  *          each different byte present.  The byte is shown first in
  13.  *          printable OR octal form, then the hexadecimal equivalent.
  14.  *          The third column is frequency.  The fourth column shows
  15.  *          percentage of total occurrences within the file.
  16.  *
  17.  *          If the /L locations option is selected, the output file is
  18.  *          name file_name.LOC and the offsets of the first up to 8
  19.  *          occurrences follow at the end of each line.
  20.  *
  21.  *  writeup: MIR TUTORIAL ONE, topic 5
  22.  *
  23.  *  written:    Douglas Lowry   Jan 04 92
  24.  *  modified:   Douglas Lowry   Feb 15 92
  25.  *                              Mar 20 92  Ten alternative report names
  26.  *              Copyright (C) 1992 Marpex Inc.
  27.  *              Compiled with STACK = 16000
  28.  *
  29.  *  For further information contact
  30.  *              Innotech Inc., 110 Silver Star Blvd., # 107,
  31.  *              Scarborough, Ontario  Canada   M1V 5A2
  32.  *              Tel.  416 321-3838   FAX  416 321-0095
  33.  *
  34.  *  This program is free software; you may redistribute it and/or
  35.  *  modify it under the terms of the GNU General Public License as
  36.  *  published by the Free Software Foundation; either version 2 of
  37.  *  the License, or (at your option) any later version.
  38.  *
  39.  *  This program is distributed in the hope that it will be useful,
  40.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  41.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  42.  *  GNU General Public License for more details.
  43.  *
  44.  *  You should have received a copy of the GNU General Public
  45.  *  License (file LICENSE.WP or LICENSE.ASC) along with this program;
  46.  *  if not, write to the Free Software Foundation, Inc.,
  47.  *  675 Mass Ave, Cambridge, MA 02139, USA.
  48.  */
  49.  
  50. #include <stdio.h>
  51. #include <fcntl.h>
  52. #include <sys\types.h>
  53. #include <sys\stat.h>
  54. #include <io.h>
  55.  
  56. #define  repeat  for(;;)
  57.  
  58. typedef     enum bool
  59.     { FALSE = 0, TRUE = 1 }  Bool ;
  60.  
  61. #define     INTAKE      2048    /*  # of bytes in input buffer  */
  62.  
  63.     void    process(), Usage_(), report(), non_exist() ;
  64.     char    *Cmdname_()     { return( "a_bytes" ) ; }
  65.  
  66. /*
  67.  *  MAIN -
  68.  */
  69.  
  70. main( argc, argv )
  71.     int     argc;
  72.     char    **argv;
  73. {
  74.     Bool    foul_up,
  75.             locations ;      /* requested by user            */
  76.     char    c10;             /* argv[1][0]                   */
  77.     int     fd,              /* file descriptor              */
  78.             file, bgn_at ;
  79.     long int     cum[ 256 ], /* accumulator for each byte    */
  80.             locn[ 256 ][ 8 ];  /*  offset of 8 occurrences of each */
  81.  
  82.     locations = FALSE ;
  83.     if( argv[1][1] == 'l' )
  84.         argv[1][1] = 'L' ;
  85.     c10 = argv[1][0] ;
  86.     if(( c10 == '-' || c10 == '/' ) && argv[1][1] == 'L' )
  87.         locations = TRUE ;
  88.     else
  89.     {
  90.         if( argc == 1 || c10 == '-' || c10 == '/' || c10 == '?' )
  91.             Usage_();
  92.     }
  93.  
  94.     bgn_at = 1 ;
  95.     if( locations )
  96.         bgn_at = 2 ;
  97.  
  98.     for( file = bgn_at ; file < argc ; file++ )
  99.     {
  100.         if(( fd = open( argv[ file ], O_RDONLY | O_BINARY )) == -1 )
  101.         {
  102.             fprintf( stderr, "Can't open file %s\n", argv[ file ] );
  103.             exit( 1 );
  104.         }
  105.  
  106.         process( fd, cum, locn, locations );
  107.  
  108.         report( cum, locn, locations, argv[file] ) ;
  109.  
  110.         if( close( fd ))
  111.             fprintf( stderr, "Problem closing %s\n", argv[ file ] );
  112.     }
  113.  
  114.     exit( 0 );
  115. }
  116.     void
  117. Usage_()
  118. {
  119.     fprintf( stderr, "\nusage:  %s [ /L ] file_name[s]\n\n\
  120.         Analyze the bytes (characters) used within any file, report\n\
  121.         the frequency of each byte present.  If the location flag /L\n\
  122.         is set, include offsets of the first 8 occurrences of each\n",
  123.                 Cmdname_() );
  124.     fprintf( stderr, "        byte pattern present.\n\n\
  125. input:  Any file[s] whatsoever.\n\n\
  126. output: file_name.BYT which contains up to 256 lines, one line for\n\
  127.         each different byte present.  The byte is shown first in\n\
  128.         printable OR octal form, then the hexadecimal equivalent.\n" );
  129.     fprintf( stderr,
  130. "        The third column is frequency.  The fourth column shows\n\
  131.         percentage of total occurrences within the file.\n\n\
  132.         If the /L locations option is selected, the output file is\n\
  133.         name file_name.LOC and the offsets of the first up to 8\n\
  134.         occurrences follow at the end of each line.\n\n" ) ;
  135.     fprintf( stderr, "writeup: MIR TUTORIAL ONE, topic 5\n\n" );
  136.     exit( 1 ) ;
  137. }
  138. /*
  139.  *  PROCESS
  140.  */
  141.     void
  142. process( fd, cum, locn, locations )
  143.     int fd;                  /*  file descriptor     */
  144.     long int     cum[ 256 ], /*  accumulator for each byte   */
  145.             locn[ 256 ][ 8 ];  /*  offset of 8 occurrences of each */
  146.     Bool    locations ;      /*  TRUE if selected by user    */
  147. {
  148.     unsigned char   buf_in[ INTAKE ];
  149.     register int    buf_len,
  150.             i;
  151.     long int     gross_locn,     /*  count of cumulative intakes */
  152.             fine_locn,
  153.             ct ;
  154.  
  155.     for( i = 0; i < 256 ; i++ )
  156.         cum[ i ] = 0;
  157.     gross_locn = 0 ;
  158.  
  159.     repeat
  160.     {
  161.         fine_locn = 0 ;
  162.         if ( ( buf_len = read( fd, buf_in, INTAKE ) ) == 0 )
  163.             break;
  164.  
  165.         for ( i= 0 ; i < buf_len ; i++ )
  166.         {
  167.             cum[ buf_in[ i ] ]++ ;
  168.             if( locations && cum[ buf_in[ i ] ] < 9 )
  169.             {
  170.                 ct = cum[ buf_in[ i ] ] - 1 ;
  171.                 locn[ buf_in [ i ] ][ ct ] = gross_locn + fine_locn ;
  172.             }
  173.             fine_locn++ ;
  174.         }
  175.  
  176.         gross_locn += buf_len ;
  177.     }
  178.  
  179.     return;
  180. }
  181. /*
  182.  *  REPORT - Output the data for analysis of one file
  183.  */
  184.     void
  185. report( cum, locn, locations, name_in )
  186.     long int     cum[ 256 ], /* accumulator for each byte    */
  187.             locn[ 256 ][ 8 ];  /*  offset of 8 occurrences of each */
  188.     Bool    locations ;      /*  TRUE if selected by user    */
  189.     char    name_in[] ;
  190. {
  191.     FILE    *fp_out ;
  192.     char    fname[20];
  193.     unsigned char   c;
  194.     double  pct,             /* % of occurrences             */
  195.             f_grand;         /* grand total bytes            */
  196.     Bool    foul_up ;
  197.     int     result,
  198.             len, i, j ;
  199.     long int   grand_total,
  200.             limit;           /*  up to 8 are tracked   */
  201.  
  202.     if( locations )
  203.         sprintf( fname, "%s.loc", name_in );
  204.     else
  205.         sprintf( fname, "%s.byt", name_in );
  206.     len = strlen( fname ) ;
  207.     for( i = 0 ; i < len ; i++ )
  208.     {
  209.         if( fname[i] == '.' )
  210.         {
  211.             if( i != len - 3 )
  212.             {
  213.                 if( locations )
  214.                     strncpy( &fname[i+1], "loc", 3 );
  215.                 else
  216.                     strncpy( &fname[i+1], "byt", 3 );
  217.             }
  218.             fname[i+4] = '\0' ;
  219.             break ;
  220.         }
  221.     }
  222.  
  223.     non_exist( fname ) ;
  224.  
  225.     if(( fp_out = fopen( fname, "w" )) == NULL )
  226.     {
  227.         fprintf( stderr, "Can't open file %s\n", fname );
  228.         return ;
  229.     }
  230.  
  231.     grand_total = 0;
  232.     foul_up = FALSE ;
  233.     for( i = 0; i < 256 ; i++ )
  234.         grand_total += cum[ i ];
  235.     f_grand = ( double ) grand_total ;
  236.  
  237.     for( i = 0; i < 256 ; i++ )
  238.     {
  239.         if( cum[ i ] )
  240.         {
  241.             c = ( unsigned char ) i;
  242.             pct = 100.0 * ( ( double ) cum[ i ] / f_grand ) ;
  243.  
  244.                 /*  For Unix version, next line should read
  245.                 if( i < 0x21 || i > 0x7e )          */
  246.  
  247.             if( i < 0x21 || i == 0x7f || i == 0xff )
  248.             {
  249.                 if( !fprintf( fp_out, "\\%03o [%02X]%7ld  %4.1f%%",
  250.                             i, i, cum[ i ], pct ) )
  251.                     foul_up = TRUE ;
  252.             }
  253.             else
  254.             {
  255.                 if( !fprintf( fp_out, "%c    [%02X]%7ld  %4.1f%%",
  256.                             c, i, cum[ i ], pct ))
  257.                     foul_up = TRUE ;
  258.             }
  259.             if( locations )
  260.             {
  261.                 fputc( ' ', fp_out );
  262.                 fputc( ' ', fp_out );
  263.                 limit = 8;
  264.                 if( cum[i] < 8 )
  265.                     limit = cum[i] ;
  266.                 for( j = 0 ; j < limit ; j++ )
  267.                     fprintf( fp_out, " %ld", locn[ i ][ j ] );
  268.             }
  269.             fputc( '\n', fp_out );
  270.         }
  271.     }
  272.  
  273.     if( foul_up )
  274.         fprintf( stderr, "Unable to write report in file %s\n", fname );
  275.     else
  276.         fprintf( stderr,
  277.             "\n\nInput size = %ld bytes.  Results are in file %s\n\n",
  278.                 grand_total, fname );
  279.     if( fclose( fp_out ))
  280.         fprintf( stderr, "Problem closing %s\n", fname );
  281.  
  282.     return ;
  283. }
  284. /*
  285.  *  NON_EXIST   Test the existence of a file; if it exists,
  286.  *              substitute digits successively for the last
  287.  *              byte in the name until a non-existent file
  288.  *              is named, or until the last digit is '9'; do
  289.  *              the same with the second last byte, for 100
  290.  *              possible combinations
  291.  */
  292.     void
  293. non_exist( fname )
  294.     char    fname[] ;
  295. {
  296.     struct  stat    buf;
  297.     Bool            gotcha ;
  298.     int             result,
  299.                     decade,     /*  batch of 10 names   */
  300.                     len, i ;
  301.  
  302.     result = stat( fname, &buf );
  303.     if( !result )  /*  data obtained = that file exists */
  304.     {
  305.         len = strlen( fname ) ;
  306.  
  307.         for( decade = 0 ; decade < 10 ; decade++ )
  308.         {
  309.             gotcha = FALSE ;
  310.             if( decade )
  311.             {
  312.                 if( fname[len-2] == '.' )
  313.                     break ;     /*  Don't mess with one digit
  314.                                     name extension              */
  315.                 fname[ len - 2 ] = '0' + decade ;
  316.             }
  317.             fname[ len - 1 ] = '0' ;
  318.  
  319.             /*  Try names ending in 0 through 9     */
  320.  
  321.             for( i = 0 ; i < 10 ; i++ )
  322.             {
  323.                 result = stat( fname, &buf );
  324.                 if( result )
  325.                 {
  326.                     gotcha = TRUE ;
  327.                     break ;
  328.                 }
  329.                 if( i < 9 )
  330.                     fname[ len - 1 ] += 1 ;
  331.             }
  332.             if( gotcha )
  333.                 break ;
  334.         }
  335.  
  336.     }
  337.     return ;
  338. }
  339.